from gear import HiddenPrints, PrintToTxt, GearInit, PlanetInit, Gear, PlanetaryGear
import numpy as np
from math import sin, cos, tan, radians, degrees, floor, sqrt, acos, atan, pi
from testgear2 import calcx1
import sys

#global f_a_table
f_a_table = [[2, 4.5, 7.5, 11, 18, 45],
             [2.5, 5.5, 9, 13.5, 21.5, 55],
             [3, 6.5, 10.5, 16.5, 26, 65],
             [3.5, 8, 12.5, 19.5, 31, 80],
             [4, 9.5, 15, 23, 37, 90],
             [5, 11, 17.5, 27, 43.5, 110],
             [6, 12.5, 20, 31.5, 50, 125],
             [7, 14.5, 23, 36, 57.5, 145],
             [8, 16, 26, 40.5, 65, 160],
             [9, 18, 28.5, 44.5, 70, 180],
             [10, 20, 31.5, 48.5, 77.5, 200],
             [11, 22, 35, 55, 87, 220]]

#global it_table
it_table = [[0.3, 0.5, 0.8, 1.2, 2, 3, 4, 6, 10, 14, 25, 40, 60, 0.1, 0.14, 0.25, 0.4, 0.6, 1, 1.4],
            [0.4, 0.6, 1, 1.5, 2.5, 4, 5, 8, 12, 18, 30, 48,
                75, 0.12, 0.18, 0.3, 0.48, 0.75, 1.2, 1.8],
            [0.4, 0.6, 1, 1.5, 2.5, 4, 6, 9, 15, 22, 36, 58,
                90, 0.15, 0.22, 0.36, 0.58, 0.9, 1.5, 2.2],
            [0.5, 0.8, 1.2, 2, 3, 5, 8, 11, 18, 27, 43, 70,
                110, 0.18, 0.27, 0.43, 0.7, 1.1, 1.8, 2.7],
            [0.6, 1, 1.5, 2.5, 4, 6, 9, 13, 21, 33, 52, 84,
                130, 0.21, 0.33, 0.52, 0.84, 1.3, 2.1, 3.3],
            [0.6, 1, 1.5, 2.5, 4, 7, 11, 16, 25, 39, 62, 100,
                160, 0.25, 0.39, 0.62, 1, 1.6, 2.5, 3.9],
            [0.8, 1.2, 2, 3, 5, 8, 13, 19, 30, 46, 74, 120,
                190, 0.3, 0.46, 0.74, 1.2, 1.9, 3, 4.6],
            [1, 1.5, 2.5, 4, 6, 10, 15, 22, 35, 54, 87, 140,
                220, 0.35, 0.54, 0.87, 1.4, 2.2, 3.5, 5.4],
            [1.2, 2, 3.5, 5, 8, 12, 18, 25, 40, 63, 100,
                160, 250, 0.4, 0.63, 1, 1.6, 2.5, 4, 6.3],
            [2, 3, 4.5, 7, 10, 14, 20, 29, 46, 72, 115, 185,
                290, 0.46, 0.72, 1.15, 1.85, 2.9, 4.6, 7.2],
            [2.5, 4, 6, 8, 12, 16, 23, 32, 52, 81, 130, 210,
                320, 0.52, 0.81, 1.3, 2.1, 3.2, 5.2, 8.1],
            [3, 5, 7, 9, 13, 18, 25, 36, 57, 89, 140, 230,
                360, 0.57, 0.89, 1.4, 2.3, 3.6, 5.7, 8.9],
            [4, 6, 8, 10, 15, 20, 27, 40, 63, 97, 155, 250, 400, 0.63, 0.97, 1.55, 2.5, 4, 6.3, 9.7]]

#global xm_Fr_table1 # 小模数齿轮径向跳动公差表1(m=0.1~0.5) 精度等级3~12
xm_Fr_table1 = [
    [3,3.5,4,4.5,5,5.5,6,6.5,7],
    [5,6,6,7,8,9,10,11,12],
    [8,9,10,11,12,13,14,16,18],
    [13,14,15,16,18,20,22,26,30],
    [18,20,22,24,26,28,32,36,40],
    [26,28,30,32,36,40,44,48,52],
    [32,34,37,40,45,50,55,60,65],
    [40,42,45,50,56,62,68,76,85],
    [50,55,60,65,70,75,85,97,105],
    [65,70,75,80,85,90,105,120,135]
]

# 小模数齿轮径向跳动公差表2(m=>0.5~<1.0) 精度等级3~12
xm_Fr_table2 = [
    [4,4.5,4.5,5,5.5,6,6.5,7,8],
    [6,7,7,8,9,10,11,12,13],
    [9,10,11,12,13,14,16,18,20],
    [15,16,17,18,20,22,24,26,30],
    [20,22,24,26,28,30,34,38,42],
    [28,30,32,36,40,44,48,52,56],
    [35,37,40,45,50,55,60,65,70],
    [44,46,50,56,62,68,74,80,90],
    [55,60,65,70,75,80,90,100,110],
    [75,80,85,90,95,100,110,120,135],
]

xm_Fr_table = [xm_Fr_table1,xm_Fr_table2]

# x方向轴线平行度误差表（轴线平面内）（小模数）
fx_table = [
    [2,3,5,6,9,11,14,18,18,18],
    [3,4,6,8,12,15,19,24,24,24],
    [4,5,8,10,15,19,24,30,30,30]
]
# y方向轴线平行度误差表（垂直平面内）（小模数）
fy_table = [
    [1,2,3,3,5,6,7,9,9,9],
    [2,2,3,4,6,8,10,12,12,12],
    [2,3,4,5,8,10,12,15,15,15]
]

def fxfy(d,m,b,it):
    '''
    当m<1时,b<=40,it=3~12
    当m>=1时,it=0~12
    :param m:分度圆直径
    :param m:模数
    :param b:齿宽
    :param it:齿轮精度
    :return:轴线平面(x)平行度误差、垂直平面(y)平行度误差
    '''
    if m>=1:#中大模数
        fbeta = F_beta(d, m, b, it)
        return fbeta,0.5*fbeta
    else:#小模数
        col = it-3
        if b<=10:
            row=0
        elif b<=20:
            row=1
        else:
            row=2
        
        return fx_table[row][col],fy_table[row][col]


def get_IT(x, IT):
    '''
    :param x:尺寸值
    :param it:精度等级，IT01输入-1；可输入-1到18
    :return:it值
    '''
    global it_table
    col = IT+1  # 公差表的第col列中查找,公差值从-1到18共20个；col=0~19
    row = -1
    xlist = [0, 3, 6, 10, 18, 30, 50, 80, 120,
             180, 250, 315, 400, 500]  # 有更大的数据，需要用到时再补充
    for i in range(len(xlist)-1):
        if xlist[i] < x and x <= xlist[i+1]:
            row = i  # 公差表的第row行中查找
            break
    if row == -1:
        print('Cannot get it, x out of range')
        sys.exit(0)

    if IT < 12:
        return it_table[row][col]
    else:
        return it_table[row][col]*1000


def b_r(d, it):
    '''
    :param d:分度圆中心距
    :param it:齿轮精度
    :return:径向进刀公差b_r
    '''

    if it == 4:
        return get_IT(d, 7)*1.26
    elif it == 5:
        return get_IT(d, 8)
    elif it == 6:
        return get_IT(d, 8)*1.26
    elif it == 7:
        return get_IT(d, 9)
    elif it == 8:
        return get_IT(d, 9)*1.26
    elif it == 9:
        return get_IT(d, 10)


def f_a(a, it):
    '''
    :param a:齿轮副工作最小中心距
    :param it:齿轮精度
    :return:中心距公差f_a
    '''
    global f_a_table
    itlist = [0, 2, 4, 6, 8, 10, 12]
    itlen = len(itlist)
    alist = [6, 10, 18, 30, 50, 80, 120, 180, 250, 315, 400, 500, 630]
    alen = len(alist)
    for i in range(itlen-1):
        if itlist[i] < it and it <= itlist[i+1]:
            col = i  # 中心距公差表的第col列中查找
            break

    for i in range(alen-1):
        if alist[i] < a and a <= alist[i+1]:
            row = i  # 中心距公差表的第row行中查找
            break

    return f_a_table[row][col]


def f_pt(d, m, it, yuanzhen=True):
    '''
    :param d:分度圆直径
    :param m:模数
    :param it:齿轮精度
    :return:单个齿距偏差f_pt
    '''

    if m >= 1:  # 中大模数
        dlist = [5, 20, 50, 125, 280, 560, 1000]  # 取自国标分界，可添加更多
        dlen = len(dlist)
        mlist = [0.5, 2, 3.5, 6, 10, 16, 25]
        mlen = len(mlist)
        for i in range(dlen-1):
            if dlist[0] == d:
                d = sqrt(dlist[0]*dlist[1])
            elif dlist[i] < d and d <= dlist[i+1]:
                d = sqrt(dlist[i]*dlist[i+1])
                break

        for i in range(mlen-1):
            if mlist[0] == m:
                m = sqrt(mlist[0]*mlist[1])
            elif mlist[i] < m and m <= mlist[i+1]:
                m = sqrt(mlist[i]*mlist[i+1])
                break

        f_pt_float = (0.3*(m+0.4*sqrt(d))+4)*(sqrt(2)**(it-5))  # 未圆整值
        if not yuanzhen:  # 不需要圆整值，一般与国标GBT10095.1-2008对应，需要圆整
            return f_pt_float
        else:
            return yuanzhenfun(f_pt_float)
    else:  # 小模数，因无规律，只取少数常用精度
        
        if it == 5:
            if d <= 20:
                return 3.5
            elif d <= 32:
                return 4
            elif d <= 50:
                return 4.5
            elif d <= 80:
                return 5
            elif d <= 125:
                return 5.5
            elif d <= 200:
                return 6
            elif d <= 400:
                return 7
        elif it == 6:
            if d <= 12:
                return 5
            elif d <= 20:
                return 5.5
            elif d <= 32:
                return 6
            elif d <= 50:
                return 6.5
            elif d <= 80:
                return 7
            elif d <= 125:
                return 8
            elif d <= 200:
                return 9
            elif d <= 315:
                return 10
            elif d <= 400:
                return 11
        elif it == 7:
            if d <= 12:
                return 7
            elif d <= 20:
                return 8
            elif d <= 32:
                return 9
            elif d <= 50:
                return 10
            elif d <= 80:
                return 11
            elif d <= 125:
                return 12
            elif d <= 200:
                return 13
            elif d <= 315:
                return 14
            elif d <= 400:
                return 15


def F_beta(d, m, b, it, yuanzhen=True):
    '''
    :param d:分度圆直径
    :param m:模数
    :param b:齿宽
    :return:螺旋线总偏差F_beta（齿向公差）
    '''
    if m >= 1:  # 中大模数
        dlist = [5, 20, 50, 125, 280, 560, 1000]  # 取自国标分界，可添加更多
        dlen = len(dlist)
        blist = [4, 10, 20, 40, 80, 160, 250, 400]
        blen = len(blist)
        for i in range(dlen-1):
            if dlist[0] == d:
                d = sqrt(dlist[0]*dlist[1])
            elif dlist[i] < d and d <= dlist[i+1]:
                d = sqrt(dlist[i]*dlist[i+1])
                break

        for i in range(blen-1):
            if blist[0] == b:
                b = sqrt(blist[0]*blist[1])
            elif blist[i] < b and b <= blist[i+1]:
                b = sqrt(blist[i]*blist[i+1])
                break
        # print(d,b)
        #fH = (0.05*sqrt(d)+0.35*sqrt(b)+4)
        #ff = (0.07*sqrt(d)+0.45*sqrt(b)+4)
        #F_beta_float = sqrt(fH**2+ff**2)*(sqrt(2)**(it-5))
        F_beta_float = (0.1*sqrt(d)+0.63*sqrt(b)+4.2)*(sqrt(2)**(it-5))
        if not yuanzhen:
            return F_beta_float
        else:
            return yuanzhenfun(F_beta_float)


def F_r(d, m, it, yuanzhen=True):
    '''
    :param d:分度圆直径
    :param m:模数
    :param it:齿轮精度
    :return:径向跳动公差F_r
    '''
    if m >= 1:  # 中大模数
        dlist = [5, 20, 50, 125, 280, 560, 1000]  # 取自国标分界，可添加更多
        dlen = len(dlist)
        mlist = [0.5, 2, 3.5, 6, 10, 16, 25]
        mlen = len(mlist)
        for i in range(dlen-1):
            if dlist[0] == d:
                d = sqrt(dlist[0]*dlist[1])
            elif dlist[i] < d and d <= dlist[i+1]:
                d = sqrt(dlist[i]*dlist[i+1])
                break

        for i in range(mlen-1):
            if mlist[0] == m:
                m = sqrt(mlist[0]*mlist[1])
            elif mlist[i] < m and m <= mlist[i+1]:
                m = sqrt(mlist[i]*mlist[i+1])
                break

        F_r_float = (0.24*m+sqrt(d)+5.6)*(sqrt(2)**(it-5))
        if not yuanzhen:
            return F_r_float
        else:
            return yuanzhenfun(F_r_float, precise=(1, 0.5, 0.5))
    else:
        if m<=0.5:
            mi = 0
        else:
            mi = 1
        dlist = [0,12,20,32,50,80,125,200,315,400]
        for i in range(len(dlist)):
            if dlist[i]<d and d<=dlist[i+1]:
                col = i
                break
        row = it-3
        
        return xm_Fr_table[mi][row][col]


def F_i_jing(d, m, it, yuanzhen=True):
    '''
    :param d:分度圆直径
    :param m:模数
    :param it:齿轮精度
    :return:径向综合偏差F''i
    '''
    if m >= 1:  # 中大模数
        dlist = [5, 20, 50, 125, 280, 560, 1000]  # 取自国标分界，可添加更多
        dlen = len(dlist)
        mlist = [0.2, 0.5, 0.8, 1, 1.5, 2.5, 4, 6, 10]
        mlen = len(mlist)
        for i in range(dlen-1):
            if dlist[0] == d:
                d = sqrt(dlist[0]*dlist[1])
            elif dlist[i] < d and d <= dlist[i+1]:
                d = sqrt(dlist[i]*dlist[i+1])
                break

        for i in range(mlen-1):
            if mlist[0] == m:
                m = sqrt(mlist[0]*mlist[1])
            elif mlist[i] < m and m <= mlist[i+1]:
                m = sqrt(mlist[i]*mlist[i+1])
                break

        F_i_jing_float = (3.2*m+1.01*sqrt(d)+6.4)*(sqrt(2)**(it-5))
        if not yuanzhen:
            return F_i_jing_float
        else:
            return yuanzhenfun(F_i_jing_float, precise=(1, 0.5, 0.5))


def f_i_jing(d, m, it, yuanzhen=True):
    '''
    :param d:分度圆直径
    :param m:模数
    :param it:齿轮精度
    :return:一齿径向综合偏差f''i
    '''
    if m >= 1:  # 中大模数
        dlist = [5, 20, 50, 125, 280, 560, 1000]  # 取自国标分界，可添加更多
        dlen = len(dlist)
        mlist = [0.2, 0.5, 0.8, 1, 1.5, 2.5, 4, 6, 10]
        mlen = len(mlist)
        for i in range(dlen-1):
            if dlist[0] == d:
                d = sqrt(dlist[0]*dlist[1])
            elif dlist[i] < d and d <= dlist[i+1]:
                d = sqrt(dlist[i]*dlist[i+1])
                break

        for i in range(mlen-1):
            if mlist[0] == m:
                m = sqrt(mlist[0]*mlist[1])
            elif mlist[i] < m and m <= mlist[i+1]:
                m = sqrt(mlist[i]*mlist[i+1])
                break

        f_i_jing_float = (2.96*m+0.01*sqrt(d)+0.8)*(sqrt(2)**(it-5))
        if not yuanzhen:
            return f_i_jing_float
        else:
            return yuanzhenfun(f_i_jing_float, precise=(1, 0.5, 0.5))


def yuanzhenfun(x, precise=(1, 0.5, 0.1)):
    (p1, p2, p3) = precise
    if x > 10:
        return round(x/p1)*p1
    elif 5 <= x and x < 10:
        return round(x/p2)*p2
    elif x < 5:
        return round(x/p3)*p3


def get_Eb(gr:Gear,flag_72=1,fenpei='auto'):
    '''
    :param flag_72:是否减去径向跳动对公法线长度的影响
    :param fenpei:'auto' or 'average'，分配齿厚上偏差的方式
    :param b:齿厚
    :return:公法线偏差（如果是内齿轮则是量柱测量距偏差）
    '''
    m = gr.m
    alpha = gr.alpha
    jbmin = 2/3*(0.06+0.0005*gr.a_work+0.03*m)*1000
    fpt1 = f_pt(gr.d1, m, 6)
    fpt2 = f_pt(gr.d2, m, 6)
    Fbeta1 = F_beta(gr.d1, m, gr.b1, 6) # 齿厚b1b2
    Fbeta2 = F_beta(gr.d2, m, gr.b2, 6)
    Fbeta = max(Fbeta1, Fbeta2)
    fa12 = f_a(gr.a_work, 6)
    jbn = sqrt(cos(alpha)**2*(fpt1**2+fpt2**2) + 2.104*Fbeta**2)
    Ess = -(jbmin+jbn)/(2*cos(alpha))-fa12*tan(alpha)
    Fr1 = F_r(gr.d1, m, 6)
    Fr2 = F_r(gr.d2, m, 6)
    br1 = b_r(gr.d1, 6)
    br2 = b_r(gr.d2, 6)
    Ts1 = sqrt(Fr1**2+br1**2)*2*tan(alpha)
    Ts2 = sqrt(Fr2**2+br2**2)*2*tan(alpha)
    if fenpei=='auto':
        k = gr.d1**(1/3) / gr.d2**(1/3)#按比例分配齿厚上偏差Es1:Es2=k,Es1+Es2=(k+1)*Es2
    elif fenpei=='average':
        k=1
    Es2 = -(jbmin+jbn+2*fa12*sin(alpha))/(k+1)/cos(alpha)
    Es1 = k*Es2
    Ei2 = Es2 - Ts2
    Ei1 = Es1 - Ts1
    
    Ebs1 = Es1*cos(alpha)-flag_72*0.72*Fr1*sin(alpha)
    Ebi1 = Ei1*cos(alpha)+flag_72*0.72*Fr1*sin(alpha)
    
    if gr.InitStruct.types == 'wai':#外啮合时大齿轮仍然采用公法线长度
        Ebs2 = Es2*cos(alpha)-flag_72*0.72*Fr2*sin(alpha)
        Ebi2 = Ei2*cos(alpha)+flag_72*0.72*Fr2*sin(alpha)
        
        return ((Ebs1,Ebi1),(Ebs2,Ebi2))
        
    else:#内齿轮采用
        #alphatm = inv_1(-gr.Dm2/gr.db2+2*tan(alpha)*gr.x2/gr.z2+pi/2/gr.z2+inv(alpha))
        Eys2 = Es2*cos(alpha)/sin(gr.alphatm[1]) 
        Eyi2 = Ei2*cos(alpha)/sin(gr.alphatm[1])
        if gr.z2 % 2 ==1:
            Eys2*=cos(pi/2/gr.z2)
            Eyi2*=cos(pi/2/gr.z2)
    
        return ((Ebs1,Ebi1),(Eys2,Eyi2))
    

if __name__ == "__main__":
    for it in range(13):

        # print(f_pt(10,1.5,it))
        #print('%.1f\t%.1f'%(F_beta(10, 1.5, 5, it),F_beta(10, 1.5, 15, it)))
        #print(F_r(10, 1, it))
        #print(F_i_jing(10, 1, it))
        #print(f_i_jing(10, 1, it))
        pass

    init1 = PlanetInit(Dm=[None,None,3])

    #planet1 = PlanetaryGear(1.75, 18, 44, 108, 0.5863, 0.691, 0.830, init1)
    pt1 = PlanetaryGear(1.75, 18, 45, 108, 0.393, 0.0285, 0.45, init1)
    
    
    g13 = pt1.gear_ac
    g32 = pt1.gear_cb
    
    Errsi = get_Eb(g13)
    
    print(g13.E[0]+Errsi[0][0]/1000,g13.E[0]+Errsi[0][1]/1000)
    
    print(g13.E[1]+Errsi[1][0]/1000,g13.E[1]+Errsi[1][1]/1000)
    Errsi32 = get_Eb(g32,flag_72=1)
    print(g32.E[0]+Errsi32[0][0]/1000,g32.E[0]+Errsi32[0][1]/1000)
    
    print(g32.E[1],Errsi32[1])
    print(g32.E[1]-Errsi32[1][1]/1000,g32.E[1]-Errsi32[1][0]/1000)
    
    print(F_r(18, 0.6, 9))
    print(fxfy(1.75*18, 1.75,40, 6))
    
    print(Errsi,Errsi32)
    
    m=0.8
    z1=18
    z3=45
    z2=108
    print(F_r(m*z1,m,6))